import bpy
from typing import List
from ...addon.naming import FluidLabNaming
from ...libs.functions.object import rm_ob
from .basic_store_objects import StoredObjects
from bpy.types import PropertyGroup, UIList, Object
from .common_list_methods import FLUIDLAB_CommonList
from ...libs.functions.get_common_vars import get_common_vars
from ...libs.functions.collections import remove_collection_if_is_empty
from bpy.props import StringProperty, IntProperty, CollectionProperty, BoolProperty, PointerProperty


""" Fluids Forces Groups List """


class FLUIDLAB_UL_draw_fluids_froces(UIList):

    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
        
        if not item.id_name or item.force.name not in context.view_layer.objects:
            layout.prop(item, "remove", text="Clear", icon='X')
            return
        
        left_sect = layout.row(align=True)
        
        # left_sect.prop(item, "label_txt", text="", emboss=False)
        left_sect.prop(item.force, "name", text="", emboss=False)

        # Right Section:
        right_sect = left_sect.row(align=True)
        right_sect.alignment = 'RIGHT'
        
        # Visible icon:
        right_sect.prop(item, "visible", text="", icon='HIDE_OFF' if item.visible else 'HIDE_ON', emboss=False)

        # Remove icon:
        rm_button = right_sect.row(align=True)
        rm_button.alert = True
        rm_button.prop(item, "remove", text="", emboss=False, icon='X')



class FluidForcesListItem(PropertyGroup):
    label_txt: StringProperty(name="Name")
    id_name: StringProperty(name="ID")
    force: PointerProperty(type=Object)
    force_type: StringProperty(name="ForceType")
    
    childrens: CollectionProperty(type=StoredObjects)
    def add_child(self, ob:Object) -> None:
        # prevenimos guardar objectos que ya esten guardados:
        if not any(ob_item.ob == ob for ob_item in self.childrens):
            _item = self.childrens.add()
            _item.ob = ob
    
    @property
    def get_childrens(self):
        return [child.get_ob for child in self.childrens]
        
    def do_remove(self, context):
        
        fluid_forces_groups = get_common_vars(context, get_fluid_forces_groups=True)
        ff_group_active = fluid_forces_groups.active
        
        if ff_group_active:
            forces_list = ff_group_active.forces

            # Si es de tipo custom no lo eliminamos, (si es generated es un empty y si lo eliminamos):
            if self.force_type == 'GENERATED':
                rm_ob(self.force)
            else:
                field = self.force.field 
                field.type = 'NONE'

                # deslinko de donde este:
                [coll.objects.unlink(self.force) for coll in self.force.users_collection if coll.name != 'RigidBodyWorld']
                
                # lo linco a su collection:
                context.view_layer.layer_collection.collection.objects.link(self.force)

            # Lo quitamos del listado:
            forces_list.remove_item(self.id_name)
            forces_list.list_index = forces_list.length-1 if not forces_list.is_void else 0
    
        remove_collection_if_is_empty(context, FluidLabNaming.FluidLab)

    remove: BoolProperty(
        default=False, 
        update=do_remove
    )

    def visible_update(self, context):

        visibility = not self.visible
        self.force.hide_set(visibility)
        
        # los Force Fields tiene un handler y sus hijos las fuerzas, por eso:
        childrens = self.force.children_recursive
        if len(childrens) > 0:
            for child in childrens:
                if not child.type == 'EMPTY':
                    continue
                child.hide_set(visibility)

    visible: BoolProperty(
        default=True, 
        update=visible_update
    )


class FluidForcesList(PropertyGroup, FLUIDLAB_CommonList):

    def list_index_update(self, context):
        item = self.active
        if not item:
            return
        
        bpy.ops.object.select_all(action='DESELECT')
        if item.force.name in context.view_layer.objects:
            item.force.select_set(True)
    
    list_index: IntProperty(name="Layer List", description="The Layer List", default=-1, update=list_index_update)
    list: CollectionProperty(type=FluidForcesListItem)


    # Fluid Groups List Methods:
    def add_item(self, item_id:str, label_txt:str, force_ob:Object, childrens:List[Object]=None, force_type:str=None) -> FluidForcesListItem:

        item = self.list.add()
        item.id_name = item_id
        item.label_txt = label_txt
        item.force = force_ob

        if force_type:
            item.force_type = force_type

        if childrens:
            [item.add_child(ob) for ob in childrens]
                
        # seteamos el ultimo elemento como activo:
        self.list_index = self.length-1

        return item
    
    @property
    def get_all_forces(self):
        return [item.force for item in self.list]